package kvraft

import (
	"sync"
)

type StateMachine struct {
	mu     sync.Mutex
	KV     map[string]string
	Client map[int64]Request
}

type Request struct {
	ID    int
	Reply string
	ch    chan string
}

func (sm *StateMachine) CheckAndCreateRequest(ClientID int64) (ok bool) {
	sm.mu.Lock()
	defer sm.mu.Unlock()
	if _, ok = sm.Client[ClientID]; !ok {
		sm.Client[ClientID] = Request{ch: make(chan string)}
	}
	return
}

func (sm *StateMachine) SaveResult(ClientID int64, RequestID int, Result string) {
	sm.mu.Lock()
	defer sm.mu.Unlock()
	request := sm.Client[ClientID]
	request.SaveResult(RequestID, Result)
}

func (r *Request) SaveResult(RequestID int, Result string) {
	r.ID = RequestID
	r.Reply = Result
}

func (sm *StateMachine) isRequested(ClientID int64, RequestID int) (result string, isRequest bool) {
	sm.mu.Lock()
	defer sm.mu.Unlock()
	client, ok := sm.Client[ClientID]
	if ok && client.ID == RequestID {
		result = client.Reply
		isRequest = true
	} else {
		isRequest = false
	}
	return
}

func (sm *StateMachine) get(key string) (value string) {
	sm.mu.Lock()
	defer sm.mu.Unlock()
	value = sm.KV[key]
	return
}

func (sm *StateMachine) put(key string, value string) {
	sm.mu.Lock()
	defer sm.mu.Unlock()
	sm.KV[key] = value
}

func (sm *StateMachine) append(key string, value string) {
	sm.mu.Lock()
	defer sm.mu.Unlock()
	if _, ok := sm.KV[key]; ok {
		sm.KV[key] = sm.KV[key] + value
	} else {
		sm.KV[key] = value
	}
	//DPrintf("append result %v", sm.KV[key])
}
